package com.pattern.beforeclass.proxy;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

/**
 * @Description
 * @Author Ping
 * @Date 2022/4/4 11:01
 **/
public class CompositeDemo {

    public static void main(String args[]) {
//        AbstractNode bigNode = new CompositeNode() ;
//        AbstractNode lessBigNode = new CompositeNode() ;
//        lessBigNode.add(new LeafNode())
//                 .add(new LeafNode())
//                .add(new LeafNode()) ;
//        bigNode.add(lessBigNode)
//                .add(new LeafNode()) ;
//        bigNode.printNodeCost();
//        bigNode.reduce(100) ;

        MyFile fileDir = new FileDir() ;
        fileDir.addFile(new TextFile())
                .addFile(new FileDir().addFile(new TextFile())) ;
        fileDir.killVirus();

    }


}

abstract class AbstractNode {
    private static int ID = 0 ;
    protected int id ;
    protected LinkedList<AbstractNode> childrenNodes ;
    protected int cost ;

    public AbstractNode() {
        this.id = ID++;
        this.childrenNodes = new LinkedList<>( ) ;
        this.cost = 0 ;
    }

    public AbstractNode add(AbstractNode child) {
        this.childrenNodes.add(child) ;
        this.cost += child.getCost() ;
        return this ;
    }
    public void printNodeCost() {
        for (AbstractNode child : this.childrenNodes) {
            child.printNodeCost();
        }
    }
    public int getCost() {
        return this.cost ;
    }

    public abstract int reduce(int paidCost) ;
}

class CompositeNode extends AbstractNode {

    @Override
    public int reduce(int paidCost) {
        for (AbstractNode child : this.childrenNodes) {
          paidCost = child.reduce(paidCost) ;
          if (paidCost == 0) {
              break ;
          }
        }

        return paidCost;
    }
}
class LeafNode extends AbstractNode {
    public LeafNode() {
        this.cost = new Random().nextInt(100) ;
    }
    @Override
    public void printNodeCost() {
        System.out.println("ID: " +this.id + ", COST: " + this.cost) ;
    }

    @Override
    public int reduce(int paidCost) {
        if (paidCost > this.cost) {
            paidCost -= this.cost ;
            this.cost = 0 ;
            System.out.println("Reducded:" + this.cost + " , left: " + (paidCost )) ;
            return paidCost ;
        }
        this.cost -= paidCost ;
        System.out.println("GOOD: the debit was paid off by Node " + this.id) ;
        return  0 ;
    }
}

abstract class MyFile {
    private static int ID = 0 ;
    List<MyFile> files ;
    int id ;

    public MyFile() {
        this.files = new ArrayList<> ();
        this.id = ID++;
    }

    public MyFile addFile(MyFile file) {
        files.add(file) ;
        return this ;
    }
    public abstract void killVirus() ;
}
class FileDir extends MyFile {
    @Override
    public void killVirus() {
        for (MyFile file : files) {
            file.killVirus();
        }
    }
}
class TextFile extends MyFile {
    @Override
    public void killVirus() {
        System.out.println("TEXT FILE " + this.id + " was scanned.") ;
    }
}